#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_

#include <cstdint>
#include <cstring>
#include <iostream>
#include <mutex>
#include <thread>

// clang-format off
#define _RINGBUFFER_IDLE_LEN_(r, w, size)           (w >= r) ? (size + r - w - 1)                       : (r - w - 1)
#define _RINGBUFFER_FILL_LEN_(r, w, size)           (w >= r) ? (w - r)                                  : (size + w - r)
#define _RINGBUFFER_BEHIND_LEN_(r, w, size)         (size - w)
#define _RINGBUFFER_BEHIND_IDLE_LEN_(r, w, size)    (w >= r) ? (r == 0) ? (size - w - 1) : (size - w)   : (r - w - 1)
#define _RINGBUFFER_BEHIND_FILL_LEN_(r, w, size)    (w >= r) ? (w - r)                                  : (size - r)

#define RINGBUFFER_IDLE_LEN()                       _RINGBUFFER_IDLE_LEN_(r, w, size)
#define RINGBUFFER_FILL_LEN()                       _RINGBUFFER_FILL_LEN_(r, w, size)
#define RINGBUFFER_BEHIND_LEN()                     _RINGBUFFER_BEHIND_LEN_(r, w, size)
#define RINGBUFFER_BEHIND_IDLE_LEN()                _RINGBUFFER_BEHIND_IDLE_LEN_(r, w, size)
#define RINGBUFFER_BEHIND_FILL_LEN()                _RINGBUFFER_BEHIND_FILL_LEN_(r, w, size)

#define RINGBUFFER_UPDATE(rw, step, size)           ((rw + step) >= size) ? (rw + step - size) : (rw + step)
// clang-format on

class ringbuffer {
private:
    uint8_t* buf; // 环形队列首地址
    int size; // 环形队列大小
    int r; // 读指针偏移
    int w; // 写指针偏移
    int lastw; // 上一次的写指针偏移
    int llastw; // 上上一次的写指针偏移
    bool inited; // 是否初始化标记
    std::mutex mtx; // 互斥锁

public:
    ringbuffer();
    ringbuffer(int size);
    ~ringbuffer();

    int set(int size);
    int read(uint8_t* obuf, int olen);
    int readr(int* pr, uint8_t* obuf, int olen);
    int write(uint8_t* ibuf, int ilen);
    int ridx_get();
    int widx_get();
    int last_widx_get();
    int llast_widx_get();
    bool is_empty();
    bool is_full();
    int idle_length_get();
    int fill_length_get();
    void lock();
    void unlock();
};

#endif